package com.ruoyi.common.config.pay;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;

/**
 * 请求客户端
 * Created by zouhl on 2018/3/1.
 */
public class RequestClient {


    private static HttpHeaders DEFAULT_HEADERS = new HttpHeaders() {
        {
            add("Content-Type", "application/json;charset=UTF-8");
        }
    };

    public static ObjectMapper JSON_MAPPER;

    public static ObjectMapper getJsonMapper() {
        if (JSON_MAPPER == null) {
            synchronized (RequestClient.class) {
                if (JSON_MAPPER == null) {
                    ObjectMapper mapper = new ObjectMapper();
                    mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
                    mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
                    JSON_MAPPER = mapper;
                }
            }
        }
        return JSON_MAPPER;
    }

    ;
    public static String toJson(Object object) {

        try {
            return getJsonMapper().writeValueAsString(object);
        } catch (IOException e) {
            return null;
        }
    }
    public static <T> T fromJson(String jsonString, Class<T> clazz) {
        if (StringUtils.isEmpty(jsonString)) {
            return null;
        }

        try {
            return getJsonMapper().readValue(jsonString, clazz);
        } catch (IOException e) {
            return null;
        }
    }

    public static RestTemplate getRestTemplate() throws IOException {
        Integer timeOut = 20000;
        CloseableHttpClient httpClient;
        httpClient = HttpClients.custom().setMaxConnTotal(20).build();
        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
        factory.setConnectTimeout(timeOut);
        factory.setConnectionRequestTimeout(timeOut);
        factory.setReadTimeout(timeOut);
        return new RestTemplate(factory);
    }

//    /**
//     * 发送POST请求
//     *
//     * @param url     请求地址
//     * @param request 请求报文对象（已签名）
//     * @return 响应JsonBody
//     */
//    public static Map sendPost(String url, Object request) throws Exception {
//        String reqJson = getJsonMapper().writeValueAsString(request);
//        //发送Json请求
//        HttpEntity<String> httpEntity = new HttpEntity<>(reqJson, DEFAULT_HEADERS);
//        ResponseEntity<String> responseEntity = getRestTemplate().postForEntity(url, httpEntity, String.class);
//        if (responseEntity.getStatusCode() != HttpStatus.OK) {
//            throw new Exception(ErrorCode.E_REQUEST_TFS_FAIL + ":请求失败");
//        }
//        String responseJsonBody = responseEntity.getBody();
//        if (responseJsonBody == null || responseJsonBody.isEmpty()) {
//            throw new Exception(ErrorCode.E_REQUEST_TFS_FAIL + ":请求失败");
//        }
//        return getJsonMapper().readValue(responseJsonBody, HashMap.class);
//    }

    /**
     * 发送POST请求
     *
     * @param url     请求地址
     * @param request 请求报文对象（已签名）
     * @return 响应JsonBody
     */
    public static Map sendPost1(String url, Object request) throws Exception {
        System.out.println("对外请求url=" + url);
        CloseableHttpClient httpclient = null;
        CloseableHttpResponse response = null;
        httpclient = (CloseableHttpClient) wrapClient();
        String reqJson = getJsonMapper().writeValueAsString(request);
        //发送Json请求
        HttpPost post = new HttpPost(url);
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(60000)
                .setConnectTimeout(60000)
                .setConnectionRequestTimeout(60000)
                .build();
        post.setConfig(requestConfig);
        StringEntity postingString = new StringEntity(reqJson, "utf-8");// json传递
        post.setEntity(postingString);
        post.setHeader("Content-type", "application/json");
        post.setProtocolVersion(HttpVersion.HTTP_1_0);
        post.addHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_CLOSE);
        response = httpclient.execute(post);
        org.apache.http.HttpEntity httpEntity = response.getEntity();
        String result = EntityUtils.toString(httpEntity);
        EntityUtils.consume(httpEntity);
        response.close();
        if (result == null || result.isEmpty()) {
            throw new Exception(ErrorCode.E_REQUEST_TFS_FAIL + ":请求失败");
        }
        return getJsonMapper().readValue(result, HashMap.class);
    }

    //绕过证书
    public static HttpClient wrapClient() {
        try {
            SSLContext ctx = SSLContext.getInstance("TLSv1.2");
            X509TrustManager tm = new X509TrustManager() {
                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                @Override
                public void checkClientTrusted(X509Certificate[] arg0,
                                               String arg1) throws CertificateException {
                }

                @Override
                public void checkServerTrusted(X509Certificate[] arg0,
                                               String arg1) throws CertificateException {
                }
            };
            ctx.init(null, new TrustManager[]{tm}, null);
            SSLConnectionSocketFactory ssf = new SSLConnectionSocketFactory(
                    ctx, NoopHostnameVerifier.INSTANCE);
            CloseableHttpClient httpclient = HttpClients.custom().setMaxConnTotal(100).setMaxConnPerRoute(10)
                    .setSSLSocketFactory(ssf).build();
            return httpclient;
        } catch (Exception e) {
            e.printStackTrace();
            return HttpClients.createDefault();
        }
    }

    /**
     * 发送POST请求
     *
     * @param url     请求地址
     * @param request 请求报文对象（已签名）
     * @return 响应JsonBody
     */
    public static Map sendPostQiYu(String url, Object request) throws Exception {
        CloseableHttpClient httpclient = null;
        CloseableHttpResponse response = null;
        httpclient = (CloseableHttpClient) wrapClient();
        String reqJson = getJsonMapper().writeValueAsString(request);
        //发送Json请求
        HttpPost post = new HttpPost(url);
        StringEntity postingString = new StringEntity(reqJson, "utf-8");// json传递
        post.setEntity(postingString);
        post.setHeader("Content-type", "application/json;charset=utf-8");
        response = httpclient.execute(post);
        String result = EntityUtils.toString(response.getEntity());
        if (result == null || result.isEmpty()) {
            throw new Exception(ErrorCode.E_REQUEST_TFS_FAIL + ":请求失败");
        }
        return getJsonMapper().readValue(result, HashMap.class);
    }

    /**
     * 发送POST请求
     *
     * @param url     请求地址
     * @param request 请求报文对象（已签名）
     * @return 响应JsonBody
     */
    public static Map sendPost(String url, Object request) throws Exception {
        //这里转了json格式报文
        String reqJson = getJsonMapper().writeValueAsString(request);
        System.out.println("POST:URL=" +url);
        System.out.println("POST:REQ=" +reqJson);

        //发送请求
        HttpEntity<String> httpEntity = new HttpEntity<>(reqJson, DEFAULT_HEADERS);
        ResponseEntity<String> responseEntity = getRestTemplate().postForEntity(url, httpEntity, String.class);
        if (responseEntity.getStatusCode() != HttpStatus.OK) {
            System.out.println("请求失败，返回码:{}"+responseEntity.getStatusCode());
            throw new Exception("99999" + ":请求失败");
        }
        String responseJsonBody = responseEntity.getBody();
        System.out.println("返回结果:RSP={}"+ responseJsonBody);
        if (responseJsonBody == null || responseJsonBody.isEmpty() ) {
            throw new Exception("99999" + ":请求失败");
        }
        return getJsonMapper().readValue(responseJsonBody, HashMap.class);
    }
}
